﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Farigola.Engine.Factories;
using Farigola.Engine.SystemData;
using Farigola.Engine.SystemData.Entity;
using Farigola.Engine.SystemData.Entity.inst;
using Farigola.Engine.SystemData.Entity.Type;
using Farigola.Engine.SystemData.DataValue;

namespace Farigola.Engine
{
    /// <summary>
    /// Represents a project, its a main object in the application.
    /// All (data, processing,..) are defined in a project.
    /// 
    /// Project are in the workspace.
    /// The active project is the current project running.
    /// </summary>
    public class Project
    {
        /// <summary>
        /// The factory to build all object: workspace, project, and all
        /// domain objects of the application.
        /// </summary>
        private Factory _factory;

        /// <summary>
        /// The unique errors manager of the engine application.
        /// Provided to main object in the engine (workspace, project,...).
        /// </summary>
        //private ErrorMgr _errorMgr;

        /// <summary>
        /// Manager of tasks activity in the application (trace)
        /// Manage alos errors occurs in the engine.
        /// </summary>
        private AppActivityMgr _appActivityMgr;

        /// <summary>
        /// For (only) builtin types and data.
        /// provided by the workspace.
        /// </summary>
        //private SystemDataMgr _systemDataMgr;

        /// <summary>
        /// typeMgr for types created in the project
	    /// (!) types and data are placed in the datatree under the root folder.
	    /// the type mgr is only to accelerate accessing types.
        /// </summary>
        //private TypeMgr _typeMgr;
	
        /// <summary>
        /// The object to find instances in the entities of the project.
	    /// scan entities from the root folder.
	    /// The finder will be active after root folders will be created.
        /// </summary>
        //private EntityFinder _entityFinder;

        /// <summary>
        /// The date time of the creation of the project.
        /// </summary>
        //private DateTime _dateCreation;

        /// <summary>
        /// the id of the project, to differentiate projects.
        /// </summary>
        //private EntityId _id;
	
        /// <summary>
        /// The name of the project.
        /// Can not be null or empty.
        /// </summary>
        //private String _name;

	    /**
	     * The root folder of data contained in the project.
	     * has no parent (= null).
	     * name is:  $$$prj_root 
         * 
         * has only 2 childs: 
         *   $$$prj_root_system    system/internal data of the project
         *   $$$prj_root_user        user data, types and entities
	     */
	    //private EntInstFolder _rootFolder;
	
	    /**
	     * The root folder for data system.
	     * child of the root folder of the project.
	     * name is: $$$prj_root_system    system/internal data of the project
	     * 
	     */
	    //private EntInstFolder _rootSystemFolder;

	    /**
	     * The root folder of user data.
	     * child of the root folder of the project.
	     * 
	     * name is: $$$prj_root_user        user data, types and entities
	     */
	    //private EntInstFolder _rootUserFolder;

        /// <summary>
        /// The structure of the proejct, and also low-level methods.
        /// </summary>
        private ProjectStruct _projectStruct;

        //---------------------------------------------------------------------
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="factory"></param>
        /// <param name="errorMgr"></param>
        public Project(ProjectStruct projectStruct)
        {
            _projectStruct = projectStruct;
            //_dateCreation = DateTime.Now;

            if (_projectStruct == null)
                return;

            _factory = _projectStruct.GetFactory();

            _appActivityMgr = _projectStruct.GetAppActivityMgr();

    	    // get the existing mgr, createed by the workspace 
    	    //_systemDataMgr= _factory.GetSystemDataMgr();
    	
    	    // create a specific mgr
    	    //_typeMgr= _factory.CreateTypeMgr();

    	    // create the entity finder
            //_entityFinder = _factory.CreateEntityFinder(_projectStruct.GetSystemDataMgr(), _typeMgr); 
        }

        //=====================================================================
        #region Checks methods.

        ////---------------------------------------------------------------------
        ///// <summary>
        ///// Check the 3 root folders.
        ///// do a basic test.
        ///// </summary>
        ///// <returns></returns>
        //public bool CheckInternalAllRootFolder(){
        //    if(_rootFolder == null)
        //        return false;
		
        //    if(_rootSystemFolder == null)
        //        return false;
        //    if(_rootUserFolder== null)
        //        return false;
        //    return true;
        //}

        //---------------------------------------------------------------------
        /// <summary>
        /// Check the workspace internal content, after init.
	    /// a basic check, if an error occurs, return false.
        /// 
        /// TODO: add parameter errListCode
        /// </summary>
        /// <returns></returns>
        public bool CheckInternal(out string errListCode){
            errListCode = "";

            if (_projectStruct == null)
                return false;
            return _projectStruct.CheckInternal(out errListCode);
	    }

        #endregion

        //=====================================================================
        #region Get/Set methods.

        //---------------------------------------------------------------------
        public ProjectStruct GetProjectStruct()
        {
            return _projectStruct;
        }

        //---------------------------------------------------------------------
        public bool SetId(EntityId id)
        {
            return _projectStruct.SetId(id);
        }

        //---------------------------------------------------------------------
        public EntityId GetId()
        {
            return _projectStruct.GetId();
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Set a date of creation of the project, used when project are load.
        /// </summary>
        /// <param name="dateCre"></param>
        public void SetDateCreation(DateTime dateCre)
        {
            _projectStruct.SetDateCreation(dateCre);
        }

        //---------------------------------------------------------------------
        public bool SetName(string name)
        {
            return _projectStruct.SetName(name);
        }

        //---------------------------------------------------------------------
        public string GetName()
        {
            return _projectStruct.GetName();
        }


        //---------------------------------------------------------------------
        public DateTime GetDateCreation()
        {
            return _projectStruct.GetDateCreation();
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// exp:
        /// "dd/MM/yyyy HH:mm:ss"
        /// </summary>
        /// <param name="format"></param>
        /// <returns></returns>
        public string GetDateCreationStr(string format)
        {
            return _projectStruct.GetDateCreationStr(format);
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Return the main root folder of the project,*has no parent (=null). 
        /// </summary>
        /// <returns></returns>
        public EntInstFolder GetRootFolder(){
		    return _projectStruct.GetRootFolder();
	    }
	
	    public EntInstFolder GetRootUserFolder(){
            return _projectStruct.GetRootUserFolder();
	    }
	
	    public EntInstFolder GetRootSystemFolder(){
            return _projectStruct.GetRootSystemFolder();
	    }

        //---------------------------------------------------------------------
        /// <summary>
        /// return the tool to find entities in the project.
        /// </summary>
        /// <returns></returns>	
	    public EntityFinder GetEntityFinder(){
            return _projectStruct.GetEntityFinder();
	    }

        //---------------------------------------------------------------------
        public Factory GetFactory()
        {
            return _factory;
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Return the type class of the inst class.
        /// </summary>
        /// <param name="instClass"></param>
        /// <returns></returns>
        public EntTypeClass GetTypeClassOfInstClass(EntInstClass instClass){
		    if(instClass==null)
			    return null;
		
		    return instClass.getEntTypeClass();
	    }

        ////---------------------------------------------------------------------
        //public bool SetRootFolder(EntInstFolder rootFolder)
        //{
        //    // check the root folders
        //    if (rootFolder == null)
        //        return false;

        //    // is already set, error
        //    if (_rootFolder != null)
        //        return false;

        //    // set the root folder
        //    _rootFolder = rootFolder;
        //    return true;
        //}

        ////---------------------------------------------------------------------
        ///// <summary>
        ///// Set all root folders, a root and 2 root childs.
        ///// Need all to make special link to each root. 
        /////  
        ///// $$$prj_root, 
        /////  		$$$prj_root_system, 
        ///// 		$$$prj_root_user		all user entities comes here.
        /////
        ///// </summary>
        ///// <param name="rootFolder"></param>
        ///// <returns></returns>
        //public bool SetAllRootFolder(EntInstFolder rootFolder)
        //{
        //    // check the root folders
        //    if (rootFolder == null)
        //        return false;

        //    // is already set, error
        //    if (_rootFolder != null)
        //        return false;

        //    // set the root folder
        //    _rootFolder = rootFolder;

        //    // set 2 others root folder, user and system
        //    _rootSystemFolder = (EntInstFolder)_rootFolder.FindChildByName(EntityDef.prjRootSystemFolderName);
        //    _rootUserFolder = (EntInstFolder)_rootFolder.FindChildByName(EntityDef.prjRootUserFolderName);

        //    // provide the root folder to the entity finder of the project
        //    _entityFinder.SetProjectRootFolder(_rootFolder);

        //    return true;
        //}


        #endregion

        //=====================================================================
        #region Is methods.

        //---------------------------------------------------------------------
        /// <summary>
        /// Return true if the inst is an instance string.
        /// </summary>
        /// <param name="inst"></param>
        /// <returns></returns>
        public bool IsTypeString(EntInstBase inst){
		    return _projectStruct.GetSystemDataMgr().IsTypeString(inst);
	    }
	
        //---------------------------------------------------------------------
        /// <summary>
        /// Return true if the inst is an instance class.
        /// </summary>
        /// <param name="inst"></param>
        /// <returns></returns>
        public bool IsTypeClass(EntInstBase inst){
            return _projectStruct.GetSystemDataMgr().IsTypeClass(inst);
	    }

        #endregion

        //=====================================================================
        #region Create DataValue instances methods.

        //---------------------------------------------------------------------
        /// <summary>
        /// Create a data value string.
        /// </summary>
        /// <param name="val"></param>
        /// <returns></returns>
        public DataValueString CreateDataValueString(String val){
		    if(val == null)
			    return null;
		
		    //create a data value
		    DataValueString dvVal = _factory.GetFactoryDataValue().CreateDataValueString();
		
		    // set the string value to data value object
		    bool res= SetValToDataValueString(dvVal, val);		
		    if(!res)
			    return null;
		
		    // create
		    return dvVal;
	    }

        //---------------------------------------------------------------------
        /// <summary>
        /// Create a data value int.
        /// </summary>
        /// <param name="val"></param>
        /// <returns></returns>
        public DataValueInt CreateDataValueInt(int val)
        {
            if (val == null)
                return null;

            //create a data value
            DataValueInt dvVal = _factory.GetFactoryDataValue().CreateDataValueInt();

            // set the string value to data value object
            bool res = SetValToDataValueInt(dvVal, val);
            if (!res)
                return null;

            // create
            return dvVal;
        }

        #endregion

        //=====================================================================
        #region Attach/detach entity instances/type class methods.

        ////---------------------------------------------------------------------
        ///// <summary>
        ///// Attach the entity (instance or type) to its folder parent.
        ///// and for folder, set the parent.
        ///// </summary>
        ///// <param name="parentFolder"></param>
        ///// <param name="ent"></param>
        ///// <returns></returns>
        //private bool AttachEntityToParentFolder(EntInstFolder parentFolder, EntityBase ent){
        //    bool res;
    	
        //    // do basic checks
        //    if(parentFolder == null)
        //        return false;
    	
        //    if(ent == null)
        //        return false;
    	
        //    // todo: do it better! manage the return...
        //    res= parentFolder.AddChild(ent);

        //    // if the ent child is an ent inst folder, set the parent
        //    if(ent is EntInstFolder)
        //        (ent as EntInstFolder).SetParentFolder(parentFolder);
    	
        //    return res;
        //}
	
        ////---------------------------------------------------------------------
        ///// <summary>
        ///// Attach the entity instance to its folder parent.
        ///// </summary>
        ///// <param name="parentFolder"></param>
        ///// <param name="entInst"></param>
        ///// <returns></returns>
        //private bool AttachEntInstToParentFolder(EntInstFolder parentFolder, EntInstBase entInst){
        //    return AttachEntityToParentFolder(parentFolder, entInst);
        //}
    
        ////---------------------------------------------------------------------
        ///// <summary>
        ///// Attach the entity type class to its folder parent.
        ///// </summary>
        ///// <param name="parentFolder"></param>
        ///// <param name="ent"></param>
        ///// <returns></returns>
        //private bool AttachEntTypeClassToParentFolder(EntInstFolder parentFolder, EntTypeClassBase ent){
        //    return AttachEntityToParentFolder(parentFolder, ent);
        //}
        #endregion


        ////=====================================================================
        //// Create entity instances basic type methods.
	
        ////---------------------------------------------------------------------
        ///// <summary>
        ///// Create an entity instance.
        ///// Do some checks before create.
        ///// If the folderParent is null, attach the inst under the root folder.
        ///// Only for basic type: string, int,...
        /////  
        ///// its a low-level method.
        ///// </summary>
        ///// <param name="parentFolder"></param>
        ///// <param name="entType"></param>
        ///// <param name="name"></param>
        ///// <returns></returns>
        //public EntInstBasicBase createEntInstBasicBase(EntInstFolder parentFolder, EntTypeBase entType, String name){
        //    bool res;
		
        //    // if the parent folder is null, set the root folder user
        //    EntInstFolder fold;
        //    if (parentFolder == null)            
        //        fold= _rootFolder;            
        //    else            
        //        fold= parentFolder;
        
        //    // the parent folder must be present in the project
        //    // todo: utiliser l'EntityFinder

        //    // check the type, must be a type basic (the method parameter must be generic)
        //    if(!(entType is EntTypeBasicBase))
        //        return null;
        
        //    // check if the name is right
        //    if(!_factory.GetFactoryCommon().checkSyntaxName(name))
        //        return null;
        
        //    // check that the name is not used by a "brother" entity, under the parent folder 
        //    if(_entityFinder.FindEntityByName(EntityFinder.FindSystemUserType.All, parentFolder, name, false) != null)
        //        return null;
        
        //    // now create the entity instance, depending on type
        //    EntInstBasicBase inst=_factory.GetFactoryEntity().CreateEntInstBasicBase(entType, name);

        //    // error?
        //    if(inst==null)
        //        return null;
        
        //    // attach the entity to its folder parent
        //    res= AttachEntInstToParentFolder(fold,inst);
        //    if(!res)
        //        return null;
        
        //    // ok the entity instance was created and attach to its parent
        //    return inst;
        //}
	
	
        ////---------------------------------------------------------------------
        ///**
        // * create a folder under a parent folder.
        // * 
        // * if the parent folder is null, its the root folder user.
        // *  
        // * @param parentFolder
        // * @param name
        // * @return
        // */
        //public EntInstFolder createEntInstFolder(EntInstFolder parentFolder, String name){
        //    bool res;
		
        //    // if the parent folder is null, set the root folder user
        //    EntInstFolder fold;
        //    if (parentFolder == null)            
        //        fold= _rootFolder;            
        //    else            
        //        fold= parentFolder;
        
        //    // the parent folder must be present in the project
        //    // todo: utiliser l'EntityFinder

        
        //    // check if the name is right
        //    if(!_factory.GetFactoryCommon().checkSyntaxName(name))
        //        return null;
        
        //    // check that the name is not used by a "brother" entity, under the parent folder 
        //    if(_entityFinder.FindEntityByName(EntityFinder.FindSystemUserType.All, parentFolder, name, false) != null)
        //        return null;
        
        //    // now create the entity instance, depending on type
        //    EntInstFolder inst=_factory.GetFactoryEntity().CreateEntInstFolder(name);

        //    // error?
        //    if(inst==null)
        //        return null;
        
        //    // attach the entity to its folder parent
        //    res= AttachEntInstToParentFolder(fold,inst);
        //    if(!res)
        //        return null;
        
        //    // ok the entity instance was created and attach to its parent
        //    return inst;
        //}

        //---------------------------------------------------------------------
        public EntInstFolder createEntInstFolder(EntInstFolder parentFolder, string name)
        {
            return _projectStruct.createEntInstFolder(parentFolder, name);
        }

        //---------------------------------------------------------------------
	    /**
	     * create a folder under a parent folder.
	     * 
	     * if the parent folder is null, its the root folder user.
	     *  
	     * @param parentFolder
	     * @param name
	     * @return
	     */
	    public EntInstFolder createEntInstFolder(string name){
		    // create an inst folder
            EntInstBase inst = _projectStruct.createEntInstFolder(GetRootUserFolder(), name);
            return (EntInstFolder)inst;
	    }

        //---------------------------------------------------------------------
        /**
         * Create a string  entity instance.
         * 
         * @param parentFolder
         * @param name
         * @return
         */
	    public EntInstString createEntInstString(EntInstFolder parentFolder, string name){
            EntInstBase inst = _projectStruct.createEntInstBasicBase(parentFolder, _projectStruct.GetSystemDataMgr().FindEntTypeByName(EntityDef.TypeStringName), name);
            return (EntInstString)inst;
	    }

        //---------------------------------------------------------------------
        /**
         * Create a string  entity instance, by default under the root folder user. 
         * 
         * @param parentFolder
         * @param name
         * @return
         */
	    public EntInstString createEntInstString(string name){
            EntInstBasicBase inst = _projectStruct.createEntInstBasicBase(GetRootUserFolder(), _projectStruct.GetSystemDataMgr().FindEntTypeByName(EntityDef.TypeStringName), name);
            return (EntInstString)inst;
	    }
	

	    /**
	     * create a string under the root folder user. 
	     * @param dvStr
	     * @return
	     */
	    public EntInstString createEntInstString(string name, DataValueString dvStr){
		    // create an entity instance string
            EntInstBase inst = _projectStruct.createEntInstBasicBase(GetRootUserFolder(), _projectStruct.GetSystemDataMgr().FindEntTypeByName(EntityDef.TypeStringName), name);
            EntInstString instStr= (EntInstString)inst;
            if(instStr == null)
        	    return null;
        
		    // check the data value string
            if(dvStr == null)
        	    return null;

            // set the data value string to the entity
            bool res= SetValToDataValueString(instStr, dvStr);
            if(res)
        	    return instStr;
        
            return null;
	    }

        //=====================================================================
        // Create entity type class methods.

        ////---------------------------------------------------------------------
        ///**
        // * Create an entity type class (type class or type class anonym).
        // * Do some checks before create.
        // * 
        // * low-level
        // * @param parentFolder
        // * @param entType
        // * @param name
        // * @return
        // */
        //public EntTypeClassBase createEntTypeClassBase(EntInstFolder parentFolder, String typeClassBaseName, String name)
        //{
        //    bool res;
		
        //    // if the parent folder is null, set the root folder user
        //    EntInstFolder fold;
        //    if (parentFolder == null)            
        //        fold= _rootFolder;            
        //    else            
        //        fold= parentFolder;
        
        //    // the parent folder must be present in the project
        //    // todo: utiliser l'EntityFinder

        //    // check if the name is right
        //    if(name == null)
        //        return null;
        //    name = name.Trim();
        //    if(name.Length == 0)
        //        return null;
        
        //    // check if the name is not used by another type class entity, in all the project, from the root folder
        //    EntTypeClassBase typeClass= _entityFinder.findEntTypeClassByName(EntityFinder.FindSystemUserType.All, GetRootFolder(),name,true);
        //    if(typeClass!=null)
        //        return null;
        	
        //    // now create the entity type class (stad or anonym)
        //    typeClass=_factory.GetFactoryEntity().CreateEntTypeClassBase(typeClassBaseName, name);
        	
        //    // error?
        //    if(typeClass==null)
        //        return null;
        
        //    // attach the entity to its folder parent
        //    res= AttachEntTypeClassToParentFolder(fold,typeClass);
        //    if(!res)
        //        return null;
        
        //    // ok the entity type class was created and attach to its parent
        //    return typeClass;
        //}
	
        //---------------------------------------------------------------------
	    /**
	     * create a type class, is empty has no data member.
	     * 
	     * @param parentFolder
	     * @param name
	     * @return
	     */
	    public EntTypeClass createTypeClass(EntInstFolder parentFolder, String name)
        {
		    EntTypeClassBase ent = _projectStruct.createEntTypeClassBase(parentFolder, typeof(EntTypeClass).ToString(), name);
            return (EntTypeClass)ent;
	    }

        //---------------------------------------------------------------------
	    /**
	     * create a type class anonym (a structure), is empty has no data member.
	     * 
	     * @param parentFolder
	     * @param name
	     * @return
	     */
	    public EntTypeClass createTypeClassAnonym(EntInstFolder parentFolder, String name)
        {
            EntTypeClassBase ent = _projectStruct.createEntTypeClassBase(parentFolder, typeof(EntTypeClassAnonym).ToString(), name);
            return (EntTypeClass)ent;
	    }

        //---------------------------------------------------------------------
        /// <summary>
        /// Create a type class, under the root folder user.
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public EntTypeClass CreateTypeClass(String name)
        {
		    return createTypeClass(GetRootUserFolder(), name);
	    }

        ////---------------------------------------------------------------------
        ///// <summary>
        ///// Add a data member to a type class.
        ///// </summary>
        ///// <param name="typeClass"></param>
        ///// <param name="nameDM"></param>
        ///// <param name="typeDM"></param>
        ///// <returns></returns>
        //public EntTypeClassDataMember AddTypeClassDataMember(EntTypeClassBase typeClass, String nameDM, EntTypeBase typeDM)
        //{
        //    // check the typeClass, must be not null 
        //    if(typeClass == null)
        //        return null;
        //    // check the typeClass, must be present in the project
        //    // todo:
		
        //    // check the name of the DM
        //    if(!_factory.GetFactoryCommon().checkSyntaxNameTypeClassDataMember(nameDM))
        //        return null;
    	
        //    // check that a DM with the same name doesn't exists
        //    if(_entityFinder.findTypeClassDataMemberByName(typeClass, nameDM) != null)
        //        return null;
				
        //    // create the data member of the type class, set the name and the type
        //    EntTypeClassDataMember typeClassDM= _factory.GetFactoryEntity().CreateEntTypeClassDataMember(typeDM, nameDM);
        //    if(typeClassDM==null)
        //        return null;
        
        //    // add the created DM to the typeClass
        //    if(!typeClass.addDataMember(typeClassDM))
        //        return null;
        
        //    // return the created typeClass data member
        //    return typeClassDM;
        //}

        //---------------------------------------------------------------------
        /// <summary>
        /// Add a data member to a type class.
        /// </summary>
        /// <param name="typeClass"></param>
        /// <param name="nameDM"></param>
        /// <param name="typeNameDM"></param>
        /// <returns></returns>
        public EntTypeClassDataMember AddTypeClassDataMember(EntTypeClassBase typeClass, String nameDM, String typeNameDM)
        {		
		    // get the type of the data Member, by the name
            EntTypeBase typeClassDM = _projectStruct.GetSystemDataMgr().FindEntTypeByName(typeNameDM);
            if(typeClassDM==null)
        	    return null;
        
            // check that the type is possible for the type class data member
            // todo:
        
            // create the data member
            return _projectStruct.AddTypeClassDataMember(typeClass, nameDM, typeClassDM);
	    }

        //=====================================================================
        #region Create entity instances class methods.

        ////---------------------------------------------------------------------
        ///// <summary>
        ///// Create the instance class empty (with no inst DM).
        ///// create instclass std or anonym.
        /////
        ///// </summary>
        ///// <param name="parentFolder"></param>
        ///// <param name="systOrUser"></param>
        ///// <param name="entType"></param>
        ///// <param name="name"></param>
        ///// <returns></returns>
        //public EntInstClass createEntInstClassEmpty(EntInstFolder parentFolder, EntityDef.TypeSystOrUser systOrUser, EntTypeBase entType, String name)
        //{
        //    bool res;
		
        //    // if the parent folder is null, set the root folder user
        //    EntInstFolder fold;
        //    if (parentFolder == null)            
        //        fold= _rootFolder;            
        //    else            
        //        fold= parentFolder;
        
        //    // the parent folder must be present in the project
        //    // todo: utiliser l'EntityFinder

        //    // check the type, must be a type basic (the method parameter must be generic)
        //    if(!(entType is EntTypeClassBase))
        //        return null;
        
        //    // check if the name is right
        //    if(!_factory.GetFactoryCommon().checkSyntaxName(name))
        //        return null;
        
        //    // check that the name is not used by a "brother" entity, under the parent folder 
        //    if(_entityFinder.FindEntityByName(EntityFinder.FindSystemUserType.All, parentFolder, name, false) != null)
        //        return null;
        
        //    // now create the entity instance, depending on type
        //    EntInstClass inst=_factory.GetFactoryEntity().CreateEntInstClassEmpty(systOrUser, entType, name);

        //    // error?
        //    if(inst==null)
        //        return null;
        
        //    // attach the entity to its folder parent
        //    res= AttachEntInstToParentFolder(fold,inst);
        //    if(!res)
        //        return null;
        
        //    // ok the entity instance was created and attach to its parent
        //    return inst;
        //}
    
        ////---------------------------------------------------------------------
        ///**
        // * Create one data member instance of the inst class.
        // * 
        // * @param instClass
        // * @param typeClassDM
        // * @return
        // */
        //public bool createInstClassDataMember(EntInstClass instClass, EntTypeClassDataMember typeClassDM)
        //{
        //    if(instClass==null)
        //        return false;
    	
        //    if(typeClassDM==null)
        //        return false;
    	
        //    // create the DM inst of the inst class (not attach the DM to the inst class)
        //    EntInstBase instDM= _factory.GetFactoryEntity().CreateInstClassDataMember(instClass, typeClassDM);    	
        //    if(instDM==null)
        //        return false;
    	
        //    // attach it to the ent class
        //    return _factory.GetFactoryEntity().AttachEntInstDataMemberToInstClass(instClass, typeClassDM, instDM);
        //}

        ////---------------------------------------------------------------------
        ///**
        // * create all instances data member of the instance class.
        // * 
        // * @param instClass
        // * @return
        // */
        //public bool createInstClassAllDataMember(EntInstClass instClass)
        //{
        //    bool res;
    	
        //    if(instClass==null)
        //        return false;
    	
        //    // scan all typeDM
        //    EntTypeClass typeClass=instClass.getEntTypeClass();
        //    foreach(EntTypeClassDataMember typeClassDM in typeClass.listDataMember()){
        //        // create the ent inst class DM and attach it
        //        res= createInstClassDataMember(instClass, typeClassDM);
        //        // stop on the first error found
        //        if(!res)
        //            return false;
        //    }
        //    // ok DM inst of the inst class are created
        //    return true;
        //}

        //---------------------------------------------------------------------
	    /**
	     * create an instance class standard, under the root parent.
	     * If the folderParent is null, attach the inst under the root folder.
	     * 
	     * @param parentFolder
	     * @param name
	     * @param typeClassName
	     * @return
	     */
	    public EntInstClass createEntInstClass(EntInstFolder parentFolder, EntityDef.TypeSystOrUser systOrUser, EntTypeClass typeClass, String name)
        {        
            // ok create the instance class empty (with no inst DM)
		    EntInstClass instClass = _projectStruct.createEntInstClassEmpty(parentFolder, systOrUser, typeClass, name);
            if(instClass==null)
        	    return null;
        
            // now create all instances data member of the instance class
            _projectStruct.createInstClassAllDataMember(instClass);
        
            // return the created inst class (with dm instances created)
            return instClass;
	    }

        //---------------------------------------------------------------------
	    /**
	     * create an instance class standard, under the root parent.
	     * If the folderParent is null, attach the inst under the parent folder.
	     * 
	     * @param parentFolder
	     * @param name
	     * @param typeClassName
	     * @return
	     */
        public EntInstClass createEntInstClass(EntInstFolder parentFolder, EntityDef.TypeSystOrUser systOrUser, String typeClassName, String name)
        {
		    // convert systOrUser to FindSystOrUser
		    // todo: par la factory common??
            EntityFinder.FindSystemUserType findSystOrUser = EntityFinder.FindSystemUserType.User;

		    // get the type class, by the name, check only user objects
            EntTypeClass typeClass= _projectStruct.GetEntityFinder().FindEntTypeClassByName(findSystOrUser, typeClassName);		
            if(typeClass==null)
        	    return null;
        
            return createEntInstClass(parentFolder,systOrUser, typeClass, name);
	    }

	
        //---------------------------------------------------------------------
	    /**
	     * create an instance class standard, under the root parent.
	     * If the folderParent is null, attach the inst under the parent folder.
	     * 
	     * @param parentFolder
	     * @param name
	     * @param typeClassName
	     * @return
	     */
	    public EntInstClass createEntInstClass(EntInstFolder parentFolder, String name, String typeClassName)
        {
		    return createEntInstClass(parentFolder, EntityDef.TypeSystOrUser.User, typeClassName, name);
	    }
	
        //---------------------------------------------------------------------
	    /**
	     * create an instance class standard, under the root folder user by default.
	     * 
	     * @param parentFolder
	     * @param name
	     * @param typeClassName
	     * @return
	     */
	    public EntInstClass createEntInstClass(String name, String typeClassName)
        {
		    return createEntInstClass(GetRootUserFolder(), typeClassName, name);
	    }
        #endregion

        //=====================================================================
        #region Create entity instances class anonym methods.

        ////---------------------------------------------------------------------
        ///// <summary>
        ///// Add a DM inst to a entity instance class anonym.
        ///// </summary>
        ///// <param name="instClassAnonym"></param>
        ///// <param name="typeDM"></param>
        ///// <param name="nameDM"></param>
        ///// <returns></returns>
        //public EntInstBase AddInstClassAnonymDataMember(EntInstClassAnonym instClassAnonym, EntTypeBase typeDM, String nameDM)
        //{
        //    if(instClassAnonym==null)
        //        return null;
		
        //    // check that the inst class is present in the project, search from the root folder
        //    // todo:
		
        //    // check the syntax name of the inst DM 
        //    if(!_factory.GetFactoryCommon().checkSyntaxName(nameDM))
        //        return null;

        //    // check that the name is not used by another inst DM of the inst
        //    if(instClassAnonym.FindEntInstDataMemberByName(nameDM) != null)
        //        // sorry, an instDM with this name already exists
        //        return null;

        //    // check that is possible to create an instDM with this type
        //    // todo:  limitation, only type basic (string,...) is possible today
        //    // todo: ask to factoryEntity
		
        //    EntInstBase entInstDM=null;
		
        //    // is the type is type basic?
        //    if(_factory.GetFactoryCommon().IsEntTypeBasic(typeDM))
        //        entInstDM = _factory.GetFactoryEntity().CreateEntInstBasicBase(typeDM, EntityDef.TypeSystOrUser.User, _factory.GetFactoryCommon().CreateEntityId(), nameDM);
        
        //    // other type?
        //    // todo:
		
        //    // -> so create inst DM basic type
        //    // ici dans une methode de la factory???

        //    if(entInstDM==null)
        //        return null;
		
        //    // attach the instDM to the inst class anonym
        //    bool res=instClassAnonym.addEntInstDataMember(entInstDM);
        //    if(!res)
        //        return null;
		
        //    // ok, return the new inst DM
        //    return entInstDM;
        //}

        ////---------------------------------------------------------------------
        ///// <summary>
        ///// Add a DM inst to a entity instance class anonym.
        ///// </summary>
        ///// <param name="instClassAnonym"></param>
        ///// <param name="typeNameDM"></param>
        ///// <param name="nameDM"></param>
        ///// <returns></returns>
        public EntInstBase AddInstClassAnonymDataMember(EntInstClassAnonym instClassAnonym, string typeNameDM, string nameDM)
        {
            return _projectStruct.AddInstClassAnonymDataMember(instClassAnonym, typeNameDM, nameDM);
        }
	
        ////---------------------------------------------------------------------
        ///// <summary>
        ///// create an instance class anonym, under the root parent.
        ///// If the folderParent is null, attach the inst under the root folder.
        ///// </summary>
        ///// <param name="parentFolder"></param>
        ///// <param name="systOrUser"></param>
        ///// <param name="name"></param>
        ///// <returns></returns>
        //public EntInstClassAnonym CreateEntInstClassAnonym(EntInstFolder parentFolder, EntityDef.TypeSystOrUser systOrUser, String name)
        //{
        //    bool res;
		
        //    // if the parent folder is null, set the root folder user
        //    EntInstFolder fold;
        //    if (parentFolder == null)            
        //        fold= _rootFolder;            
        //    else            
        //        fold= parentFolder;
        
        //    // the parent folder must be present in the project
        //    // todo: utiliser l'EntityFinder

        //    // check if the name is right
        //    if(!_factory.GetFactoryCommon().checkSyntaxName(name))
        //        return null;
        
        //    // check that the name is not used by a "brother" entity, under the parent folder 
        //    if(_entityFinder.FindEntityByName(EntityFinder.FindSystemUserType.All, parentFolder, name, false) != null)
        //        return null;
        
        //    // now create the entity instance class anonym
        //    EntInstClassAnonym inst=_factory.GetFactoryEntity().CreateEntInstClassAnonymEmpty(systOrUser, name);

        //    // error?
        //    if(inst==null)
        //        return null;
        
        //    // attach the entity to its folder parent
        //    res= AttachEntInstToParentFolder(fold,inst);
        //    if(!res)
        //        return null;
        
        //    // ok the entity instance was created and attach to its parent
        //    return inst;
        //}

        //---------------------------------------------------------------------
        /// <summary>
        /// create a inst class anonym.
        /// </summary>
        /// <param name="parentFolder"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        public EntInstClassAnonym createEntInstClassAnonym(EntInstFolder parentFolder, String name)
        {
            return _projectStruct.CreateEntInstClassAnonym(parentFolder, EntityDef.TypeSystOrUser.User, name);		
	    }

        //---------------------------------------------------------------------
        /// <summary>
        /// create a inst class anonym.
	    /// By default, under the root folder user.
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public EntInstClassAnonym createEntInstClassAnonym(String name)
        {
            return _projectStruct.CreateEntInstClassAnonym(GetRootUserFolder(), EntityDef.TypeSystOrUser.User, name);		
	    }

        #endregion

        //=====================================================================
        #region Create entity instances structure (list,...).

        ////---------------------------------------------------------------------
        ///// <summary>
        ///// create an inst list of items, under the provided root folder.
        ///// Here items are Entities instances, (not DataValue).
        ///// </summary>
        ///// <param name="parentFolder"></param>
        ///// <param name="systOrUser"></param>
        ///// <param name="entTypeItem"></param>
        ///// <param name="listName"></param>
        ///// <returns></returns>
        //public EntInstStructList CreateEntInstStructListEnt(EntInstFolder parentFolder, EntityDef.TypeSystOrUser systOrUser, EntTypeBase entTypeItem, string listName)
        //{
        //    if (parentFolder == null)
        //        parentFolder = GetRootSystemFolder();

        //    // the parent folder must be present in the project
        //    // todo: utiliser l'EntityFinder

        //    // check the type of items
        //    if (entTypeItem == null)
        //        return null;

        //    // only type basic are possible today, no class, (and of course no folder!)
        //    if (!_factory.GetFactoryCommon().IsEntTypeBasic(entTypeItem))
        //        return null;


        //    // check if the name is right
        //    if (!_factory.GetFactoryCommon().checkSyntaxName(listName))
        //        return null;

        //    // check that the name is not used by a "brother" entity, under the parent folder 
        //    if (_entityFinder.FindEntityByName(EntityFinder.FindSystemUserType.All, parentFolder, listName, false) != null)
        //        return null;

        //    // now create the entity instance list
        //    EntInstStructList instList = _factory.GetFactoryEntity().CreateEntInstStructList(systOrUser, entTypeItem, listName);

        //    // error?
        //    if (instList == null)
        //        return null;

        //    // attach the entity to its folder parent
        //    bool res = AttachEntInstToParentFolder(parentFolder, instList);
        //    if (!res)
        //        return null;

        //    // ok the entity instance was created and attached to its parent
        //    return instList;
        //}

        ////---------------------------------------------------------------------
        ///// <summary>
        ///// create an inst list of items, under the provided root folder.
        ///// Here items are data value, (not Entities instances).
        ///// </summary>
        ///// <param name="parentFolder"></param>
        ///// <param name="systOrUser"></param>
        ///// <param name="entTypeItem"></param>
        ///// <param name="listName"></param>
        ///// <returns></returns>
        //public EntInstStructList CreateEntInstStructList(EntInstFolder parentFolder, EntityDef.TypeSystOrUser systOrUser, DataValueType dataValueType, string listName)
        //{
        //    if (parentFolder == null)
        //        parentFolder = GetRootSystemFolder();

        //    // the parent folder must be present in the project
        //    // todo: utiliser l'EntityFinder

        //    // check the type of items
        //    if (dataValueType == DataValueType.Undefined)
        //        return null;

        //    // check if the name is right
        //    if (!_factory.GetFactoryCommon().checkSyntaxName(listName))
        //        return null;

        //    // check that the name is not used by a "brother" entity, under the parent folder 
        //    if (_entityFinder.FindEntityByName(EntityFinder.FindSystemUserType.All, parentFolder, listName, false) != null)
        //        return null;

        //    // now create the entity instance list
        //    EntInstStructList instList = _factory.GetFactoryEntity().CreateEntInstStructList(systOrUser, dataValueType, listName);

        //    // error?
        //    if (instList == null)
        //        return null;

        //    // attach the entity to its folder parent
        //    bool res = AttachEntInstToParentFolder(parentFolder, instList);
        //    if (!res)
        //        return null;

        //    // ok the entity instance was created and attached to its parent
        //    return instList;
        //}

        //---------------------------------------------------------------------
        /// <summary>
        /// create an inst list of items, under the provided root folder.
        /// By default items are DataValue.
        /// </summary>
        /// <param name="entTypeItemName"></param>
        /// <param name="listName"></param>
        /// <returns></returns>
        public EntInstStructList CreateEntInstStructList(EntInstFolder parentFolder, EntityDef.TypeSystOrUser systOrUser, string typeItemName, string listName)
        {
            // get the type of data value to put in the list
            DataValueType dataValueType;
            bool res=_factory.GetFactoryDataValue().GetDataValueTypeByName(typeItemName, out dataValueType);
            if (!res)
                return null;

            return _projectStruct.CreateEntInstStructList(parentFolder, systOrUser, dataValueType, listName);
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// create an inst list of items, under the provided root folder.
        /// Here items are Entities instances, (not DataValue).
        /// </summary>
        /// <param name="entTypeItemName"></param>
        /// <param name="listName"></param>
        /// <returns></returns>
        public EntInstStructList CreateEntInstStructListEnt(EntInstFolder parentFolder, EntityDef.TypeSystOrUser systOrUser, string entTypeItemName, string listName)
        {
            // find the type of items, by the name (all: to find also buitin type linke string,...)
            EntTypeBase entTypeItem = _projectStruct.GetEntityFinder().FindEntTypeBaseByName(entTypeItemName);
            if (entTypeItem == null)
                return null;

            return _projectStruct.CreateEntInstStructListEnt(parentFolder, systOrUser, entTypeItem, listName);
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// create an inst list of items, under the provided root folder.
        /// By default items are DataValue.
        /// </summary>
        /// <param name="entTypeItemName"></param>
        /// <param name="listName"></param>
        /// <returns></returns>
        public EntInstStructList CreateEntInstStructList(EntInstFolder parentFolder, string entTypeItemName, string listName)
        {
            return CreateEntInstStructList(parentFolder, EntityDef.TypeSystOrUser.User, entTypeItemName, listName);
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// create an inst list of items, under the provided root folder.
        /// Here items are Entities instances, (not DataValue).
        /// </summary>
        /// <param name="entTypeItemName"></param>
        /// <param name="listName"></param>
        /// <returns></returns>
        public EntInstStructList CreateEntInstStructListEnt(EntInstFolder parentFolder, string entTypeItemName, string listName)
        {
            return CreateEntInstStructListEnt(parentFolder, EntityDef.TypeSystOrUser.User, entTypeItemName, listName);
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// create an inst list of items, under the root folder user by default.
        /// By default items are DataValue
        /// </summary>
        /// <param name="entTypeItemName"></param>
        /// <param name="listName"></param>
        /// <returns></returns>
        public EntInstStructList CreateEntInstStructList(string entTypeItemName, string listName)
        {
            return CreateEntInstStructList(GetRootUserFolder(), entTypeItemName, listName);		
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// create an inst list of items, under the root folder user by default.
        /// Here items are Entities instances, (not DataValue).
        /// </summary>
        /// <param name="entTypeItemName"></param>
        /// <param name="listName"></param>
        /// <returns></returns>
        public EntInstStructList CreateEntInstStructListEnt(string entTypeItemName, string listName)
        {
            return CreateEntInstStructListEnt(GetRootUserFolder(), entTypeItemName, listName);
        }

        #endregion

        //=====================================================================
        #region get/set value to basic types entity instances methods.

        //---------------------------------------------------------------------
        /// <summary>
        /// Set the string value to data value string.
        /// </summary>
        /// <param name="dvVal"></param>
        /// <param name="val"></param>
        /// <returns></returns>
        public bool SetValToDataValueString(DataValueString dvVal, string val)
        {
		    if(dvVal==null)
			    return false;
		    if(val==null)
			    return false;
		
		    return dvVal.SetValue(val);
	    }

        //---------------------------------------------------------------------
        /// <summary>
        /// Set the nit value to data value int.
        /// </summary>
        /// <param name="dvVal"></param>
        /// <param name="val"></param>
        /// <returns></returns>
        public bool SetValToDataValueInt(DataValueInt dvVal, int val)
        {
            if (dvVal == null)
                return false;
            if (val == null)
                return false;

            return dvVal.SetValue(val);
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// set a string value to data value object.
        /// </summary>
        /// <param name="instStr"></param>
        /// <param name="dvStr"></param>
        /// <returns></returns>
        public bool SetValToDataValueString(EntInstString instStr, DataValueString dvStr)
        {
		    if(instStr == null)
			    return false;
		    if(dvStr == null)
			    return false;
	
		    return instStr.SetDataValueString(dvStr);
	    }

        //---------------------------------------------------------------------
        /// <summary>
        /// Set a value to an entity string.
	    /// can't be null.

        /// </summary>
        /// <param name="entString"></param>
        /// <param name="dvVal"></param>
        /// <returns></returns>
        public bool SetValToEntInstString(EntInstString entString, DataValueString dvVal)
        {
		    if(entString == null)
			    return false;
		    if(dvVal == null)
			    return false;
		
		    // check the entity instance string, must be present in the project
		    // todo:

		    // set the data value string to the entity instance string
		    return entString.SetDataValueString(dvVal);
	    }
	
        //---------------------------------------------------------------------
        /// <summary>
        /// Set a value to an entity string.
	    /// can't be null.

        /// </summary>
        /// <param name="entString"></param>
        /// <param name="val"></param>
        /// <returns></returns>
        public bool SetValToEntInstString(EntInstString entString, String val)
        {
		    if(val == null)
			    return false;
		
		    // create a data value and set the value
		    //DataValueString dvVal = _factory.getFactoryDataValue().createDataValueString();
		    DataValueString dvVal =CreateDataValueString(val);
			
		
		    // set the string value to data value object
		    //bool res= setValToDataValueString(dvVal, val);
		
		    if(dvVal==null)
			    return false;
		
		    // create
		    return SetValToEntInstString(entString, dvVal);
	    }

        //---------------------------------------------------------------------
        /// <summary>
        /// get/return the string data value of the entity instance string.
        /// </summary>
        /// <param name="entString"></param>
        /// <returns></returns>
        public DataValueString GetDataValueFromEntInstString(EntInstString entString)
        {
		    if(entString == null)
			    return null;
		
		    //check that the entity is present in the project
            EntInstString entStringFind = _projectStruct.GetEntityFinder().FindEntInstStringById(entString.GetId());
		    if(entStringFind == null)
			    // not found, must be present
			    return null;
		
		    // get the inner data value string of the entity
		    return entString.GetDataValueString();
	    }

        //---------------------------------------------------------------------
        /// <summary>
        /// return the value (of the data value string) of the entity instance string.
        /// </summary>
        /// <param name="entString"></param>
        /// <returns></returns>
        public string GetValFromEntInstString(EntInstString entString)
        {
		    if(entString == null)
			    return null;
		
		    // extract the string data value   
		    DataValueString dvString= GetDataValueFromEntInstString(entString);
		
		    // then get the string value
		    return dvString.GetValue();
        }

        #endregion

        //=====================================================================
        #region Add/remove, updte item in struct list methods.

        //---------------------------------------------------------------------
        public bool AddItemToList(EntInstStructList instList, DataValueBase dataValue)
        {
            if (instList == null)
                return false;

            // ok type of the data value math the type of data value of the inst list
            return instList.AddItem(dataValue);
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// add a string value item to a an inst struct list.
        /// items in list can be data value string or en inst string.
        /// </summary>
        /// <param name="instList"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool AddItemToList(EntInstStructList instList, EntInstBase entInst)
        {
            if (instList == null)
                return false;

            return instList.AddItem(entInst);
        }

        #endregion
    }
}
